//-----------------------------------------------------------------------------------
// Detailed Extraction Rule Template version 1.0
//-----------------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Globalization;
using System.Xml;
using System.Xml.XPath;
using Microsoft.VisualStudio.TestTools.WebTesting;

namespace TestProject1
{
    [System.ComponentModel.DisplayName("ExtractXMLAtributeValue")]
    [System.ComponentModel.Description("XML version of the build-in Extract Atribute Value extraction rule")]
    public class ExtractXMLAtributeValue : WebTestRequestPlugin
    {
        #region Constructors
        /// <summary>
        /// standard constructor
        /// </summary>
        public ExtractXMLAtributeValue() { }
        #endregion


        #region Properties
        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        string m_attributeValue;
        [System.ComponentModel.DisplayName("Attribute Value")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.DefaultValue("")]
        public string AttributeValue
        {
            get { return m_attributeValue; }
            set { m_attributeValue = value; }
        }

        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        string m_htmlDecode;
        [System.ComponentModel.DisplayName("HTML Decode")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.DefaultValue("")]
        public string HtmlDecode
        {
            get { return m_htmlDecode; }
            set { m_htmlDecode = value; }
        }


        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        int m_index;
        [System.ComponentModel.DisplayName("Index")]
        [System.ComponentModel.Description("One based index of the element")]
        [System.ComponentModel.DefaultValue(1)]
        public int Index
        {
            get { return m_index; }
            set { m_index = value; }
        }


        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        string m_matchAttributeName;
        [System.ComponentModel.DisplayName("Match attribute name")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.DefaultValue("")]
        public string MatchAttributeName
        {
            get { return m_matchAttributeName; }
            set { m_matchAttributeName = value; }
        }

        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        string m_matchAttributeValue;
        [System.ComponentModel.DisplayName("Match attribute Value")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.DefaultValue("")]
        public string MatchAttributeValue
        {
            get { return m_matchAttributeValue; }
            set { m_matchAttributeValue = value; }
        }

        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        bool m_required;
        [System.ComponentModel.DisplayName("Required")]
        [System.ComponentModel.Description("If True, the extraction rule fails if not found.")]
        [System.ComponentModel.DefaultValue(true)]
        public bool Required
        {
            get { return m_required; }
            set { m_required = value; }
        }

        /// <summary>
        /// If True, the extraction rule fails if not found.
        /// </summary>
        string m_tagName;
        [System.ComponentModel.DisplayName("Tag name")]
        [System.ComponentModel.Description("")]
        [System.ComponentModel.DefaultValue("")]
        public string TagName
        {
            get { return m_tagName; }
            set { m_tagName = value; }
        }


        /// <summary>
        /// Contains value that was extracted.
        /// </summary>
        string m_extractedValue;
        public string ExtractedValue
        {
            get { return m_extractedValue; }
        }

        /// <summary>
        /// Contains a message that is surfaced to the user
        /// </summary>
        string m_message;
        public string ExtractMessage
        {
            get { return m_message; }
        }

        #endregion // Properties

        #region Utility Functions
        /// <summary>
        /// A sample utility function that performs the actual work of extracting values. 
        /// This demonstrates the best practice of moving most of the code out into 
        /// it's own function so you can test it from a unit test.
        /// </summary>
        /// <returns>true - value found, false - value not found, reason contains more details</returns>
        public bool Extract(string document)
        {
            ///Check that the response is not empty
            Debug.Assert(document != null);
            
            //Create XmlDocument object..
            XmlDocument doc = new XmlDocument();

            //Verify that m_index is a number greater then 1
            if (m_index < 1)
                throw new Exception("Incorrect parameter for the Index parameter. Index should be a integer number bgrater then 1.");

            //Verify that m_matchAttributeValue is blank when m_matchAttributeName is not set
            if (m_matchAttributeValue != string.Empty && m_matchAttributeName == string.Empty)
                throw new Exception("Match attribute value parameter cannot be set when Match attibute name is blank.");


            try
            {
                //Load the response into XMLDocument object
                doc.LoadXml(document);
            }
            catch (XmlException exc)
            {
                throw new Exception("Cannot load response as the XML document: " + exc.Message);
            }


            //Set the XPath attribute filter
            string xpathAttibuteFilter;
            if (m_matchAttributeName == string.Empty)
                xpathAttibuteFilter = string.Empty;
            else
                xpathAttibuteFilter = "[@" + m_matchAttributeName + "='" + m_matchAttributeValue + "']";

            //Create the XPath query
            string xpath = "//" + m_tagName + xpathAttibuteFilter + "[" + m_index + "]";

            //Execute the XPath query
            XPathNavigator nav = doc.CreateNavigator();
            XPathNodeIterator iterator = nav.Select(xpath);

            //Return false if the data has not been found
            if (!iterator.MoveNext())
                return false;

            //Set the m_extractedValue to the attibute value and return true
            m_extractedValue = iterator.Current.GetAttribute(m_attributeValue, "");
            return true;
        }
        #endregion

        #region Extract Method
        /// <summary>
        /// The Extract method.  The parameter e contains the Web test context.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void PostRequest(object sender, PostRequestEventArgs e)
        {
            /*
            try
            {
                e.Success = Extract(e.Response.BodyString);
                if (e.Success)
                {
                    e.Success = true;
                    e.WebTest.Context[this.ContextParameterName] = ExtractedValue;
                }
                else
                {
                    // If the extraction fails, set the error text that the user sees
                    e.Message = String.Format(CultureInfo.CurrentCulture, ExtractMessage);
                    //
                    // If Not required, then not finding it is ok
                    if (!Required) e.Success = true;
                }
            }
            catch (Exception ex)
            {
                e.Message = String.Format(CultureInfo.CurrentCulture, "{0}[{1}] Exception: {2}", "ExtractionRule1", this.ContextParameterName, ex.Message.ToString());
                e.Success = false;
            }
             * */
        }
        #endregion
    }
}